﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Firefly.Framework.Input
{
    public class KeyMap : InputMap, IButtonMapEx<Keys, KeyboardManager, KeyMapEventArgs>, IUpdateable
    {
        private int _lastRepeatTimeSpan;

        public int RepeatRate { get; set; }

        public KeyMap(Keys[] mappedKeys)
            : this(mappedKeys, string.Empty, 100, 0)
        {
        }

        public KeyMap(Keys[] mappedKeys, string action)
            : this(mappedKeys, action, 100, 0)
        {
        }

        public KeyMap(Keys[] mappedKeys, string action, int holdThreshold, int repeatRate)
            : base()
        {
            InputMapType = InputMapType.KeyMap;
            Action = action;
            HoldThreshold = holdThreshold;
            RepeatRate = repeatRate;
            MappedButtons = new List<Keys>();

            for (int i = 0; i < mappedKeys.Length; i++)
            {
                MappedButtons.Add(mappedKeys[i]);
            }

            InputService.Instance.RegisterInputMap(this);
        }

        #region IButtonMap Members
        
        public bool IsMapUp
        {
            get
            {
                bool status = false;

                foreach (Keys key in MappedButtons)
                {
                    if (Manager.IsButtonUp(key))
                    {
                        status = true;
                    }
                }

                return status;
            }
        }
        public bool IsMapDown
        {
            get
            {
                bool status = true;

                foreach (Keys key in MappedButtons)
                {
                    if (Manager.IsButtonUp(key))
                    {
                        status = false;
                    }
                }

                return status;
            }
        }
        public bool WasMapPressed
        {
            get
            {
                bool status = false;

                foreach (Keys key in MappedButtons)
                {
                    if (Manager.WasButtonUp(key))
                    {
                        status = true;
                    }
                }

                return (status && IsMapDown) ? true : false;
            }
        }
        public bool WasMapReleased
        {
            get
            {
                bool status = true;

                foreach (Keys key in MappedButtons)
                {
                    if (Manager.WasButtonUp(key))
                    {
                        status = false;
                    }
                }

                return (status && IsMapUp) ? true : false;
            }
        }
        public bool WasMapHeld
        {
            get
            {
                bool status = true;

                foreach (Keys key in MappedButtons)
                {
                    if (Manager.WasButtonUp(key))
                    {
                        status = false;
                    }
                }

                return (status && IsMapDown) ? true : false;
            }
        }

        #endregion

        #region IButtonMapEx Members

        public event EventHandler<KeyMapEventArgs> MapHeld;
        public event EventHandler<KeyMapEventArgs> MapPressed;
        public event EventHandler<KeyMapEventArgs> MapReleased;

        private int _millisecondsHeld;
        
        public List<Keys> MappedButtons { get; private set; }
        public int HoldThreshold { get; set; }

        private void NotifyMapHeld()
        {
            EventHandler<KeyMapEventArgs> handler = MapHeld;

            if (handler != null)
            {
                handler(this, new KeyMapEventArgs(this));
            }
        }

        private void NotifyMapPressed()
        {
            EventHandler<KeyMapEventArgs> handler = MapPressed;

            if (handler != null)
            {
                handler(this, new KeyMapEventArgs(this));
            }
        }

        private void NotifyMapReleased()
        {
            EventHandler<KeyMapEventArgs> handler = MapReleased;

            if (handler != null)
            {
                handler(this, new KeyMapEventArgs(this));
            }
        }

        #endregion

        #region IHasInputManager Members

        public KeyboardManager Manager { get; set; }

        #endregion

        #region IUpdateable Members

        public override void Update(GameTime gameTime)
        {
            if (Enabled)
            {
                if (WasMapPressed)
                {
                    _millisecondsHeld = 0;
                    NotifyMapPressed();
                }
                else if (WasMapReleased)
                {
                    NotifyMapReleased();
                }
                else if (WasMapHeld)
                {
                    _millisecondsHeld += gameTime.ElapsedRealTime.Milliseconds;

                    if (HoldThreshold > 0 && _millisecondsHeld >= HoldThreshold)
                    {
                        _lastRepeatTimeSpan += gameTime.ElapsedGameTime.Milliseconds;

                        if (RepeatRate == 0 || _lastRepeatTimeSpan >= RepeatRate)
                        {
                            NotifyMapHeld();
                            _lastRepeatTimeSpan = 0;
                        }
                    }
                }
            }
        }

        #endregion
    }
}
